const DEFAULT_TRIGGER = "shift";
const ALLOW_EVENTS = ["shift", "ctrl", "alt"];
import { flatten } from "@/utils/utils";

export const SELECTED_STATE = "selected";

export function clickSelect(G6) {
  G6.registerBehavior("click-select", {
    getDefaultCfg() {
      return {
        multiple: true,
        trigger: DEFAULT_TRIGGER,
      };
    },
    getEvents() {
      if (!this.multiple) {
        return {
          "node:click": "onClick",
          "edge:click": "onClick",
          "canvas:click": "onCanvasClick",
        };
      }
      return {
        "node:click": "onClick",
        "edge:click": "onClick",
        "canvas:click": "onCanvasClick",
        keyup: "onKeyUp",
        keydown: "onKeyDown",
      };
    },
    onClick(e) {
      const self = this;
      const item = e.item;
      const graph = self.graph;
      const autoPaint = graph.get("autoPaint");
      graph.setAutoPaint(false);

      // 当前是否选择有变化
      let selectChangeFlag = false;

      if (!self.keydown || !self.multiple) {
        const selected = this.getSelected();

        flatten(Object.values(selected)).forEach((n) => {
          if (n !== item) {
            if (n.hasState(SELECTED_STATE)) {
              selectChangeFlag = true;
              graph.setItemState(n, SELECTED_STATE, false);
            }
          }
        });
      }
      if (item.hasState(SELECTED_STATE)) {
        return;
      } else {
        if (self.shouldUpdate.call(self, e)) {
          selectChangeFlag = true;
          graph.setItemState(item, SELECTED_STATE, true);
        }
        graph.emit("nodeselectchange", { target: item, select: true });
      }
      if (selectChangeFlag) {
        this.emitSelectChange();
      }
      graph.setAutoPaint(autoPaint);
      graph.paint();
    },
    onCanvasClick() {
      if (this.keydown) {
        return;
      }

      const graph = this.graph;
      const autoPaint = graph.get("autoPaint");
      graph.setAutoPaint(false);
      const selected = this.getSelected();

      // 当前是否选择有变化
      let selectChangeFlag = false;

      flatten(Object.values(selected)).forEach((n) => {
        if (n.hasState(SELECTED_STATE)) {
          selectChangeFlag = true;
          graph.setItemState(n, SELECTED_STATE, false);
        }
      });
      if (selectChangeFlag) {
        this.emitSelectChange(true);
      }

      graph.paint();
      graph.setAutoPaint(autoPaint);
    },
    onKeyDown(e) {
      const code = e.key;
      if (ALLOW_EVENTS.indexOf(code.toLowerCase()) > -1) {
        this.keydown = true;
      } else {
        this.keydown = false;
      }
    },
    onKeyUp() {
      this.keydown = false;
    },

    getSelected() {
      return getSelected(this.graph);
    },
    emitSelectChange(isClear: boolean = false) {
      if (isClear) {
        this.selectChange([], []);
      } else {
        const graph = this.graph;
        const nodes = graph.findAllByState("node", SELECTED_STATE);
        const edges = graph.findAllByState("edge", SELECTED_STATE);
        this.selectChange(nodes, edges);
      }
    },
    selectChange(nodes: any[], edges: any[]) {
      this.graph.emit("select-change", { nodes, edges });
    },
  });
}

export function getSelected(graph: any) {
  return {
    nodes: graph.findAllByState("node", SELECTED_STATE),
    edges: graph.findAllByState("edge", SELECTED_STATE),
  };
}
